import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { HttpErrorResponse } from '@angular/common/http';

import { NzNotificationService } from 'ng-zorro-antd';
import { Subscription } from 'rxjs';

import { Store } from '@ngrx/store';
import { UserState, UserLogin } from '../../../../store';
import * as fromUser from '../../../../store/selectors/user.selector';

import { LoginParams, UserToken } from '../../../../shared/modes';
import { LocalstoreService } from '../../../../shared/services';


@Component({
  selector: 'ege-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, OnDestroy {

  loginForm: FormGroup;
  loginLoading: boolean = false;
  loginBtnText: string = '登录';

  validationMessages = {
    'username': {
      'required':      '请输入您的用户名！',
      'pattern':       '您输入的用户名格式不正确！'
    },
    'password': {
      'required':      '请输入您的密码！',
      'pattern':       '您输入的密码格式不正确！'
    }
  };

  formErrors = {
    'username': '',
    'password': ''
  };

  private subscriptions: Subscription[] = [];

  constructor(
    private store: Store<UserState>,
    private router: Router,
    private notificationService: NzNotificationService,
    private localstore: LocalstoreService
  ) { }

  ngOnInit() {
    this.buildForm();
    const getUserLogining = this.store.select(fromUser.getUserLogining).subscribe((logining: boolean) => {
      this.loading(logining);
    });
    const getUserToken = this.store.select(fromUser.getUserToken).subscribe((userToken: UserToken) => {
      userToken && this.saveUserToken(userToken);
    });
    const getUserLoginError = this.store.select(fromUser.getUserLoginError).subscribe((loginError: HttpErrorResponse) => {
      loginError && this.loadFail(loginError);
    });
    const getUserLogined = this.store.select(fromUser.getUserLogined).subscribe((logined: boolean) => {
      if(logined) {
        this.router.navigateByUrl('/');
      }
    });
    this.subscriptions = [ ...this.subscriptions, getUserLogining, getUserToken, getUserLoginError, getUserLogined];
  }

  ngOnDestroy() {
    for(let i = 0; i < this.subscriptions.length; i++) {
      this.subscriptions[i].unsubscribe();
    }
    this.subscriptions = [];
  }

  buildForm(): void {
    this.loginForm = new FormGroup({
      username: new FormControl('', [Validators.required, Validators.pattern(/^[A-Za-z0-9_]{3,20}$/)]),
      password: new FormControl('', [Validators.required, Validators.pattern(/^[A-Za-z0-9!@#$%^&*()_]{6,20}$/)]),
      remember: new FormControl(true)
    });
    this.loginForm.valueChanges.subscribe(values => {
      this.onValueChanged(values);
    });
    this.onValueChanged();
  } 

  onValueChanged(data?: any) {
    if (!this.loginForm) { return; }
    const form = this.loginForm;
    for(const field in this.formErrors) {
      this.formErrors[field] = '';
      const control = form.get(field);
      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          if(this.formErrors[field] === '') this.formErrors[field] += messages[key] + ' ';
        }
      }
    }
  }

  getFormControl(controlName: string): any {
    return this.loginForm.controls[controlName];
  }

  formMarkAsDirty(): void {
    for (const i in this.loginForm.controls) {
      this.loginForm.controls[ i ].markAsDirty();
    }
  }

  onSubmit(): void {
    this.formMarkAsDirty();
    this.onValueChanged();
    if(this.loginForm.valid) {
      const values = this.loginForm.value;
      const username = values.username;
      const password = values.password;
      const params: LoginParams = { username, password };
      this.store.dispatch(new UserLogin(params));
    }
  }

  loading(loading: boolean): void {
    this.loginLoading = loading;
    this.loginBtnText = loading ? '正在登录...' : '登录';
  }

  saveUserToken(userToken: UserToken): void {
    let date = new Date(userToken.created);
    date.setSeconds(date.getSeconds() + userToken.ttl);
    this.localstore.setItem('USER_TOKEN', userToken, date.toUTCString());
  }

  loadFail(error: HttpErrorResponse): void {
    let message: string = '登陆失败！';
    switch(error.status) {
      case 401: {
        message = '登录失败！用户名或密码输入错误，请确认后再登录。';
        break;
      }
    }
    this.notificationService.error('登录提示', message);
  }

}
